#include "Tcpserver.hpp"
#include "protocol.hpp"
#include "daemon.hpp"
#include <memory>
#include <signal.h>

using namespace ns_tcp_server;
using namespace ns_protocol;

static void Usage(const std::string proc)
{
    std::cout << "\nUsage: " << proc << " port\n"
              << std::endl;
}
Response CalculatorHelp(const Request &req)
{
    Response resp(0, 0);
    switch (req._op)
    {
    case '+':
        resp._result = req._x + req._y;
        break;
    case '-':
        resp._result = req._x - req._y;
        break;
    case '*':
        resp._result = req._x * req._y;
        break;
    case '/':
        if (req._y == 0)
            resp._code = 1; // 除0错误
        else
            resp._result = req._x / req._y;
        break;
    case '%':
        if (req._y == 0)
            resp._code = 2; // % 0错误
        else
            resp._result = req._x % req._y;
        break;
    default:
        resp._code = 3;
        break;
    }
    return resp;
}
void Calculator(int sock)
{
    std::string inbuff;
    while (true)
    {
        // 1、读取成功
        bool res = Recv(sock, &inbuff); // 读请求
        if (!res)
            break;

        // std::cout << "begin: inbuff: " << inbuff << std::endl;
        // 2、协议解析，保证得到完整的报文
        std::string package = Decode(inbuff);
        if (package.empty())
            continue;
        // std::cout << "end: inbuff: " << inbuff << std::endl;
        // std::cout << "package: " << package << std::endl;
        logMessage(NORMAL, "%s", package.c_str());
        // 3、保证是完整的报文
        Request req;
        // 4、反序列化设置req，字节流——>结构化
        req.Deserialize(package);
        // 5、业务部分
        Response resp = CalculatorHelp(req);
        // 6、序列化后返还给客户端
        std::string respString = resp.Serialize();

        // 7、添加长度信息，形成完整报文
        //  length\r\ncode result\r\n
        std::cout << "begin: respString: " << respString << std::endl;
        respString = Encode(respString);
        std::cout << "end: respString: " << respString << std::endl;
        // 8、暂时这样写，因为缓冲区不一定能装的下，一次性发不全
        Send(sock, respString);
    }
}

//./exe port
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        // exit(1);
    }
    MyDaemon();

    // 一般经验: server在编写的时候，要有较为严谨性的判断逻辑
    // 一般服务器，都是要忽略SIGPIPE信号的，防止在运行中出现非法写入的问题!
    // signal(SIGPIPE, SIG_IGN);

    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));
    server->BindServer(Calculator);

    server->Start();

    // Request req(10, 567, '+');
    // std::string str = req.Serialize();
    // std::cout << str << std::endl;
    return 0;
}